Basic Knowledge about Java

JAVA COLLECTIONS

ArrayList

参考链接 🔗

继承自List接口,允许添加多个null元素及重复元素,并保持元素插入顺序

Example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("Oh");
arrayList.add("my");
arrayList.add("gosh");
System.out.println(arrayList);
arrayList.add(0, "What's");
arrayList.add(1, "the");
arrayList.add(2, "fuck");
System.out.println(arrayList);
arrayList.remove("Oh");
System.out.println(arrayList);
arrayList.remove(0);
arrayList.remove(1);
System.out.println(arrayList);
}
}

输出:

1
2
3
4
[Oh, my, gosh]
[What's, the, fuck, Oh, my, gosh]
[What's, the, fuck, my, gosh]
[the, my, gosh]

执行arrayList.remove(0)后,位于0的新的元素是”the”,所以执行arrayList.remove(1)删除的是”fuck”。如果要按顺序删除的话,一直执行arrayList.remove(0)即可

Method

  • add(Object o)

在末端添加新元素o

1
arrayList.add("Oh");
  • add(int index, Object o)

在指定位置添加元素o

1
arrayList.add(2, "fuck"); // 2nd index, 3rd position

除此之外,还可以添加元素的集合到ArrayList中,方法是:addAll(Collection C)addAll(int index, Collection C)

  • remove(Object o)

删除元素o

1
arrayList.remove("Oh");
  • remove(int index)

删除指定位置的元素

1
arrayList.remove(0); // index 0, 1st element of the list
  • set(int index, Object o)

替换指定位置的元素

1
arrayList.set(0, "wow");
  • int indexOf(Object o)

返回元素o的索引,如果元素不存在则返回-1

1
int pos = arrayList.indexOf("Oh");
  • Object get(int index)

返回特定位置上的元素

1
String string = arrayList.get(0);
  • int size()

返回ArrayList的长度,即其中的元素个数

1
int num = arrayList.size();
  • boolean contains(Object o)

检查是否存在元素o,返回true/false

1
arrayList.contains("oh");
  • clear()

清空所有元素

1
arrayList.clear();

Initialization

  • Method 1: Initialization with Arrays.asList()
1
2
ArrayList<Type> obj = new ArrayList<Type>(
Arrays.asList(Object o1, Object o2, Object o3, ...));
  • Method 2: Anonymous inner class method to initialize ArrayList
1
2
3
4
5
6
ArrayList<T> obj = new ArrayList<T>(){{
add(Object o1);
add(Object o2);
add(Object o3);
...
}};
  • Method3: Normal way of ArrayList initialization
1
2
3
4
5
ArrayList<T> obj = new ArrayList<T>();
obj.add("Object o1");
obj.add("Object o2");
obj.add("Object o3");
...
  • Method 4: Use Collections.ncopies

给所有元素赋相同的值时适用。

1
ArrayList<T> obj = new ArrayList<T>(Collections.nCopies(count, element));

Iteration

  • For Loop
  • Foreach Loop
  • While Loop
  • Iterator
  • Enumeration
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public class Main {
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("Oh");
arrayList.add("my");
arrayList.add("gosh");
// For Loop
for (int i = 0; i < arrayList.size(); i++) {
System.out.println(arrayList.get(i));
}
// Foreach Loop
for (String str : arrayList) {
System.out.println(str);
}
// forEach()
arrayList.forEach(array -> System.out.println(array));
arrayList.forEach(System.out::println);
// While Loop
int count = 0;
while (arrayList.size() > count) {
System.out.println(arrayList.get(count));
count++;
}
// Iterator
Iterator iterator = arrayList.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
// Enumeration
Enumeration<String> enumeration = Collections.enumeration(arrayList);
System.out.println(enumeration.nextElement());
}
}
}

对于ArrayList来说,随机访问比较快。for循环中的get()方法,采用的是随机访问的方法;而iterator中的next()方法,采用的是顺序访问。因此,ArrayList适合用前者,而LinkedList则适合用后者。

Conversions

  • ArrayListString Array
1
2
3
4
5
6
7
8
// Convert to array - 1
String[] arr = new String[arrayList.size()];
for (int i = 0; i < arrayList.size(); i++) {
arr[i] = arrayList.get(i);
}
// Convert to array - 2
String[] arr1 = arrayList.toArray(new String[arrayList.size()]);
  • ArrayArrayList

当然,最基础的就是直接添加:

1
2
3
4
5
String str[] = {"s", "t", "r"};
ArrayList<String> arr = new ArrayList<>();
for (int i = 0; i < str.length; i++) {
arr.add(str[i]);
}

但是还可以更简单一点 ☞

1
2
String str[] = {"s", "t", "r"};
ArrayList<String> arr = new ArrayList<>(Arrays.asList(str));

Or ☞

1
2
3
String str[] = {"s", "t", "r"};
ArrayList<String> arr = new ArrayList<>();
Collections.addAll(arr, str);
  • LinkedListArrayList
1
2
3
4
5
LinkedList<String> linkedList = new LinkedList<>();
linkedList.add("main");
linkedList.add("activity");
List<String> list = new ArrayList<>(linkedList);

Sort

  • Collections.sort()

按照字母先后顺序或者数字从小到大的顺序排列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Main {
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("Oh");
arrayList.add("my");
arrayList.add("gosh");
Collections.sort(arrayList);
for (String str : arrayList) {
System.out.println(str);
}
}
}

输出

1
2
3
Oh
gosh
my

那么问题来了 ☞ 如何按照递减的顺序排列呢?

  • Collections.sort(arrayList, Collections.reverseOrder());

这样就是按照递减的方式排列了,或者也可以用以下方式代替 ☞

1
2
Collections.sort(arrayList);
Collections.reverse(arrayList);

当然,以上两种适用于简单的数据的排序,当ArrayList的存放的数据类型变得更为复杂时呢?

Emmm……比如说这样 ☞

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
class Book {
private String name;
private int time;
private int pages;
public Book(String name, int time, int pages) {
this.name = name;
this.time = time;
this.pages = pages;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getTime() {
return time;
}
public void setTime(int time) {
this.time = time;
}
public int getPages() {
return pages;
}
public void setPages(int pages) {
this.pages = pages;
}
}

我们已经定义了一种新的数据类型Book,现在用ArrayList来存放数据 ☞

1
2
3
4
5
6
7
8
public class Main {
public static void main(String args[]){
ArrayList<Book> arrayList = new ArrayList<>();
arrayList.add(new Book("ABC", 223, 26));
arrayList.add(new Book("DEF", 245, 24));
arrayList.add(new Book("GHI", 557, 32));
}
}

现在再用之前的方法肯定是行不通了,试试借助其他办法 ☞

  • Comparable

通过重写Comparable接口的compareTo()方法,来比较排序。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Book implements Comparable<Book> {
private String name;
private int time;
private int pages;
public Book(String name, int time, int pages) {
this.name = name;
this.time = time;
this.pages = pages;
}
...
@Override
public int compareTo(Book book) {
int page =((Book)book).getPages();
// For ascending order
return this.pages - page;
// For descending order
// return page - this.pages;
}
@Override
public String toString() {
return "[ name = " + name + ", time = " + time + ", pages = " + pages + "]";
}
}
1
2
3
4
5
6
7
8
9
10
11
12
public class Main {
public static void main(String args[]) {
ArrayList<Book> arrayList = new ArrayList<>();
arrayList.add(new Book("ABC", 223, 26));
arrayList.add(new Book("DEF", 245, 24));
arrayList.add(new Book("GHI", 557, 32));
Collections.sort(arrayList);
for (Book str : arrayList) {
System.out.println(str);
}
}
}

输出

1
2
3
[ name = DEF, time = 245, pages = 24]
[ name = ABC, time = 223, pages = 26]
[ name = GHI, time = 557, pages = 32]
  • Comparator

或者我们可以重写Comparator接口中的compare()方法来排序。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
class Book {
private String name;
private int time;
private int pages;
public Book(String name, int time, int pages) {
this.name = name;
this.time = time;
this.pages = pages;
}
...
public static Comparator<Book> compareName = new Comparator<Book>() {
@Override
public int compare(Book o1, Book o2) {
String name1 = o1.getName();
String name2 = o2.getName();
// String name = o.getName().toUpperCase();
// For ascending order
return name1.compareTo(name2);
// For descending order
// return name2.compareTo(name1);
}
};
public static Comparator<Book> compareTime = new Comparator<Book>() {
@Override
public int compare(Book o1, Book o2) {
int time1 = o1.getTime();
int time2 = o2.getTime();
return time1 - time2;
// return time2 - time1;
}
};
@Override
public String toString() {
return "[ name = " + name + ", time = " + time + ", pages = " + pages + "]";
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Main {
public static void main(String args[]) {
ArrayList<Book> arrayList = new ArrayList<>();
arrayList.add(new Book("ABC", 223, 26));
arrayList.add(new Book("DEF", 245, 24));
arrayList.add(new Book("GHI", 557, 32));
Collections.sort(arrayList, Book.compareName);
System.out.println("Sorted by name");
for (Book str : arrayList) {
System.out.println(str);
}
System.out.println("Sorted by time");
Collections.sort(arrayList, Book.compareTime);
for (Book str : arrayList) {
System.out.println(str);
}
}
}

输出

1
2
3
4
5
6
7
8
Sorted by name
[ name = ABC, time = 223, pages = 26]
[ name = DEF, time = 245, pages = 24]
[ name = GHI, time = 557, pages = 32]
Sorted by time
[ name = ABC, time = 223, pages = 26]
[ name = DEF, time = 245, pages = 24]
[ name = GHI, time = 557, pages = 32]

Remove Duplicate Elements

  • HashSet
1
2
3
4
5
6
7
8
9
10
11
12
13
public class Main {
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("The");
arrayList.add("road");
arrayList.add("not");
arrayList.add("not");
arrayList.add("taken");
HashSet<String> hashSet = new HashSet<>(arrayList);
ArrayList<String> arrayList1 = new ArrayList<>(hashSet);
System.out.println(arrayList1);
}
}

输出:

[The, not, road, taken]

删除重复元素之后,元素插入顺序会被打乱。

  • LinkedHashSet

LinkedHashSet不允许重复元素,并且会保持元素的顺序。

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Main {
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("The");
arrayList.add("road");
arrayList.add("not");
arrayList.add("not");
arrayList.add("taken");
LinkedHashSet<String> linkedHashSet = new LinkedHashSet<>(arrayList);
ArrayList<String> arrayList1 = new ArrayList<>(linkedHashSet);
System.out.println(arrayList1);
}
}

输出:

[The, road, not, taken]

Comparable & Comparator

在之前的ArrayList的排序中就已经用到了这两个接口来进行比较排序,这里主要写两者的区别。

Comparable Comparator
Package java.lang.Comparable java.util.Comparator
Implementation Class whose objects to be sorted must implement this interface Class whose objects to be sorted do not need to implement this interface
Sorting Method int compareTo(Object o1) This method compares this object with o1 object and returns a integer. Its value: positive ➣ this object > o1; zero ➣ this object = o1; negative ➣ this object < o1 int cpmpare(Object o1, Object o2) This method compares o1 with o2 and returns a integer. Its value: positive ➣ o1 > o2; zero ➣ o1 = o2; negative ➣ o1 < o2
Calling Method Collections.sort(List) Collections.sort(List, Comparator)
Sorting Logic Sorting logic must be in same class whose objects are being sorted Sorting logic is in seperate class

Java 迭代器

迭代器是一个轻量级对象,可以遍历并选择序列中的对象。

将遍历序列的操作与底层序列的结构分离,统一了对容器的访问方式。

迭代器

Iterator

只能单向移动,在遍历的时候不允许在底层集合进行增删元素的操作(通过迭代器本身操作除外)。

  • boolean hasNext()

判断是否有更多元素

  • E next()

返回下一个元素

如果没有下一个元素,则抛出NoSuchElementException异常。

  • void remove()

删除迭代器返回的底层集合的最后一个元素,只能在每次调用next()方法后使用一次

如果调用的不是迭代器中删除元素的方法,而是通过底层集合自带的删除元素的方法,会抛出UnsupportedOperationException异常。

如果在调用之前没有返回元素,会抛出IllegalStateException异常。

ListIterator

Iterator的子类,只能访问各种List类,但是功能更加强大,可以双向移动。

  • void add(E e)

  • boolean hasNext()

  • boolean hasPrevious()

  • E next()

  • int nextIndex()

  • E previous()

  • int previousIndex()

  • void remove()

  • void set(E e)

Iterator 和 Enumeration 的区别

Iterator允许在遍历的时候删除底层集合的元素

除此之外,就是方法命名更加规范,用hasNext()替代了hasMoreElements(),用next()替代了nextElement()

迭代器接口

迭代器有IteratorIterable两个接口。

1
2
3
public interface Iterable<T> {
Iterator<T> iterator();
}
1
2
3
4
5
public interface Iterator<E> {
boolean hasNext();
E next();
void remove();
}

IterableIterator接口的包装,超级接口,实现上更简洁,并且可以允许实现此接口的对象成为foreach语句的目标。除此之外,Iterable每次调用时返回一个从头开始的迭代器,多个迭代器之间互不干扰,不会出现当前迭代位置混乱的不可预知错误。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class Main implements Iterable<Book> {
private final List<Book> bList = new ArrayList<>();
@Override
public Iterator<Book> iterator() {
return new Iterator<Book> () {
private final Iterator<Book> iter = bList.iterator();
@Override
public boolean hasNext() {
return iter.hasNext();
}
@Override
public Book next() {
return iter.next();
}
@Override
public void remove() {
throw new UnsupportedOperationException("no changes allowed");
}
};
}
}

Static Import

import static com…ClassName.*(/静态方法名);

替换import com...ClassName,在使用的时候可以直接用方法名调用静态方法,而不用通过ClassName.方法名的方式。

Without Static Imports ☞

1
2
3
4
5
6
7
8
9
public class Main {
public static void main(String[] args) {
double a = Math.sqrt(4);
System.out.print(a);
}
}

Using Static Imports ☞

1
2
3
4
5
6
7
8
9
10
11
12
import static java.lang.Math.*;
import static java.lang.System.out;
public class Main {
public static void main(String[] args) {
double a = sqrt(4);
out.print(a);
}
}

Polymorphism

Explain polymorphism in one sentence ➣

Subclasses of a class can define their own unique behaviors and yet share some of the same functionality of the parents.

未完待续。。。